/* eslint-disable @iceworks/best-practices/recommend-polyfill */
/* eslint-disable no-param-reassign */
import carImg from '@/assets/car02.png';
import { useStore } from '@/hooks';
import { t } from '@lingui/macro';
import { observer } from 'mobx-react-lite';
import React, { useEffect, useRef, useState } from 'react';
import { Label, Marker } from 'react-bmapgl';
import { LINE_PROP, avgSpeed, fillLayerPoints } from '../stores/TaskMapStore';
import { DATETIME_TEXT } from '@/stores/definitions-base';
import moment from 'moment';
// import { avgSpeed, coordConvert } from '../stores/TaskMapStore';

const { BMapGL } = global;

function TraceMap() {
  const { taskMapStore: store } = useStore();
  const carRef = useRef();
  const carLabelRef = useRef();
  const layerRef = useRef();
  const newLocs = useRef([]).current; // list of GeoLocation
  // const lineRef = useRef();
  const [traceInfo, setTraceInfo] = useState({
    title: '',
    text: '',
    position: null,
  }); // 鼠标触发显示

  const [initialPoints, setInitialPoints] = useState({
    start: { lng: 0, lat: 0, speed: 0 },
    end: { lng: 0, lat: 0, speed: 0 },
    car: { lng: 0, lat: 0, speed: 0 },
  });
  const { mapRef: map } = store.mapContext;

  useEffect(() => {
    if (!store.trace?.id) return;

    const { line } = store.trace;
    const _layer = new BMapGL.GeoJSONLayer('trace', { ...LINE_PROP, dataSource: store.trace.line });
    // _layer.getData()[0].points.forEach((p, idx) => { p.latLng = { ...aryToLoc(line.coordinates[idx]), ...p.latLng }; });
    fillLayerPoints(_layer.getData()[0].points, line.coordinates);

    // console.log('_layer', _layer);

    const _path = _layer.getData()[0].points.map((p) => p.latLng);
    const start = _path[0];
    const end = _path[_path.length - 1];

    const car = store.traceKind === 0 ? end : start;
    const { lng, lat, bearing } = car;

    _layer.addEventListener('mousemove', (e) => {
      const dur = moment.duration(moment(store.trace.endTime).diff(store.trace.startTime));
      const sh = dur.hours() > 0 ? t`${dur.hours()}小时` : '';
      const sm = dur.minutes() > 0 ? t`${dur.minutes()}分钟` : '';
      setTraceInfo({
        position: e.latLng,
        text: t`任务: ${store.trace.metadata?.taskId}<br />
        出发: ${DATETIME_TEXT(store.trace.startTime)}<br />
        到达: ${DATETIME_TEXT(store.trace.endTime)}<br />
        距离: ${(store.trace.distance / 1000).toFixed(1)}公里 耗时: ${sh}${sm}<br />
        平均时速: ${(avgSpeed(_path) * 3.6).toFixed(1)}公里/小时`,
      });
    });
    _layer.addEventListener('mouseout', (_) => setTraceInfo({}));

    carRef.current.instance.setRotation(bearing);
    carRef.current.instance.setPosition(new BMapGL.Point(lng, lat));

    map.addGeoJSONLayer(_layer);
    layerRef.current = _layer;
    setInitialPoints({ start, end, car });

    const ctx = {
      carRef: carRef.current?.instance,
      carLabelRef: carLabelRef.current?.instance,
      carPoint: car,
      path: _path,
    };
    Object.assign(store.mapContext, ctx);
    map.panTo(car);

    const aniHandle = setInterval(() => processNowLocation(), 2000); // 每2秒处理一次更新

    let sub;
    (async () => {
      sub = await store.subscribeLocation({
        filter: { traceId: store.trace.id },
        onNext: (loc) => newLocs.push(loc),
      });
    })();
    return () => {
      clearInterval(aniHandle);
      _layer.destroy();
      sub?.cancel();
    };
  }, [store.trace]);

  async function processNowLocation() {
    const len = newLocs.length;
    if (len === 0) return;
    store.trace.line.coordinates.push(...newLocs.splice(0).map((l) => l.point.coordinates)); // 这里清空
    layerRef.current.setData(store.trace.line);
    const { points } = layerRef.current.getData()[0];
    const newPts = points.slice(-(len + 1));
    fillLayerPoints(newPts, store.trace.line.coordinates.slice(-(len + 1)));
    await store.locAnimation(newPts.map((p) => p.latLng), 70);
  }

  if (store.animating);

  return (
    <>
      <Marker position={initialPoints.start} icon="start" />
      {store.traceKind === 1 && <Marker position={initialPoints.end} icon="end" />}
      <Marker ref={carRef} position={initialPoints.car} icon={new BMapGL.Icon(carImg, new BMapGL.Size(38, 38))} />
      <Label ref={carLabelRef} position={initialPoints.car} text={t`时速${(initialPoints.car.speed * 3.6).toFixed(1)}公里`} offset={new BMapGL.Size(16, -16)} />
      {traceInfo.position && <Label {...traceInfo} offset={new BMapGL.Size(16, -36)} />}
    </>
  );
}

export default observer(TraceMap);
